
package com.lam.common.utils;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Objects;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.lam.common.exception.BaseException;

public class JsonUtil {
	
	private static final Logger logger = LoggerFactory.getLogger(JsonUtil.class);

	private static final ObjectMapper objectMapper = createObjectMapper(true);
	private static final ObjectMapper objectMapperWithoutNullWrite = createObjectMapper(false);

	static {
        //空值不序列化
        objectMapperWithoutNullWrite.setSerializationInclusion(JsonInclude.Include.NON_NULL);
	}
	
	private JsonUtil(){
		throw new IllegalArgumentException("util class");
	}
	
	public static <T> TypeReference<List<T>> newTypeRf() {
		return new TypeReference<List<T>>() {};
	}
	
	public static ObjectMapper getObjectMapper() {
        return objectMapper;
    }
	
	public static ObjectMapper createObjectMapper(boolean writeNull) {
		ObjectMapper objectMapper = new ObjectMapper();
		//序列换成json时,将所有的long变成string.因为js中得数字类型不能包含所有的java long值，超过16位后会出现精度丢失
//		SimpleModule simpleModule = new SimpleModule();
//		simpleModule.addSerializer(Long.class, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
//        simpleModule.addSerializer(Long.TYPE, com.fasterxml.jackson.databind.ser.std.ToStringSerializer.instance);
//        objectMapper.registerModule(simpleModule);
        
		/* 设置输入时忽略JSON字符串中存在而Java对象实际没有的属性 */
		objectMapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
		
        //去掉默认的时间戳格式
        objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
        //设置时区
        objectMapper.setTimeZone(TimeZone.getTimeZone("GMT+8"));
        //空值序列化
        objectMapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);
        //反序列化时，属性不存在的兼容处理
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //序列化时，日期的统一格式
        objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

        objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
        //反序列化的时候如果多了其他属性,不抛出异常
        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //单引号处理
        objectMapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);
        
        if(!writeNull) {
        	//空值不序列化
        	objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        }
        return objectMapper;
	}
	
	@SuppressWarnings("unchecked")
	public static Object get(Object obj, String key){
		if(obj == null){
			return null;
		}
		if(obj instanceof Map){
			return ((Map<String, Object>)obj).get(key);
		}
		return parseJSON(obj).get(key);
	}
	
	public static Map<String, Object> getJsonObject(Object obj, String key){
		return parseJSON(get(obj, key));
	}
	
	public static List<Map<String, Object>> getJsonArray(Object obj, String key){
		return parseArray(get(obj, key));
	}
	
	public static String getString(Object obj, String key){
		Object v = get(obj, key);
		if(v == null){
			return null;
		}
		return toJsonString(v);
	}
	
	public static Integer getInteger(Object obj, String key){
		Object v = get(obj, key);
		if(v == null){
			return null;
		}
		return NumberUtil.toInteger(v, null);
	}
	
	public static Long getLong(Object obj, String key){
		Object v = get(obj, key);
		if(v == null){
			return null;
		}
		return NumberUtil.toLong(v, null);
	}
	
	public static Double getDouble(Object obj, String key){
		Object v = get(obj, key);
		if(v == null){
			return null;
		}
		return NumberUtil.toDouble(v, null);
	}

	/**
	 * 将对象转换为JSON字符串
	 * 
	 * @param obj
	 * @return
	 */
	public static String toJsonString(Object obj) {
		return toJsonString(obj, true, false);
	}
	
	/**
	 * 将对象转换为JSON字符串
	 * 
	 * @param obj
	 * @param prettyFormat 是否使用格式化/美化/优雅的输出
	 * @return
	 */
	public static String toJsonString(Object obj, boolean prettyFormat) {
		return toJsonString(obj, true, prettyFormat);
	}
	
	/**
	 * 将对象转换为JSON字符串
	 * 
	 * @param obj
	 * @param writeNull 序列化是否包含空值
	 * @param prettyFormat 是否使用格式化/美化/优雅的输出
	 * @return
	 */
	public static String toJsonString(Object obj, boolean writeNull, boolean prettyFormat) {
		return toJsonString(obj, writeNull, prettyFormat, null, null);
	}
	
    /**
	 * 将对象转换为JSON字符串
	 * 
	 * @param obj
	 * @param writeNull 序列化是否包含空值
	 * @param prettyFormat 是否使用格式化/美化/优雅的输出
	 * @return
	 */
	public static String toJsonString(Object obj, boolean writeNull, boolean prettyFormat, Class<?> targetClass, Class<?> mixinSource) {
		if(obj instanceof String){
			return (String)obj;
		}
		
		try {
			ObjectMapper mapper;
			if(targetClass != null && mixinSource != null) {
				mapper = createObjectMapper(writeNull);
				mapper.addMixIn(targetClass, mixinSource);
			}else {
				mapper = writeNull ? objectMapper : objectMapperWithoutNullWrite;
			}
			
			if(prettyFormat){
				return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
			}
			
			return mapper.writeValueAsString(obj);
		} catch (Exception e) {
			logger.error("java对象转Json字符串异常", e);
			throw new BaseException("java对象转Json字符串异常", e);
		}
	}

	/**
	 * 将对象转换为对象
	 */
	public static <T> T toJavaObject(Object object, Class<T> clazz) {
		if(object == null) {
			return null;
		}
//		if(clazz.isAssignableFrom(object.getClass())) {
//			return (T)object;
//		}
		
		return toJavaObject(JsonUtil.toJsonString(object), clazz);
	}
	
	/**
	 * 将JSON字符串转换为对象
	 */
	@SuppressWarnings("unchecked")
	public static <T> T toJavaObject(String json, Class<T> clazz) {
		
		if(StringUtils.isBlank(json)) {
    		return null;
    	}
		if(clazz == Date.class) {
			return (T) DateUtil.parseDate(json);
		}
		
		try {
			return objectMapper.readValue(json, clazz);
		} catch (Exception e) {
			logger.error(e.getMessage(), e);
			throw new BaseException(e.getMessage(), e);
		}
	}
	
	/**
     * Json对象转Java对象
     * @param object
     * @param clazz
     * @param extFieldOptions 不符合下划线转驼峰形式的字段，可以在此指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
     * @return
     */
    public static <T> T toJavaObjectWithSnake(Object object, Class<T> clazz, String ... extFieldOptions) {

    	if((object = snakeCaseConvert(object, extFieldOptions)) == null || clazz == null){
    		return null;
    	}
        return toJavaObject(toJsonString(object), clazz);
    }
    
    /**
     * Json对象转Java对象
     * @param object
     * @param clazz
     * @param mappings 指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
     * @return
     */
    public static <T> T toJavaObject(Object object, Class<T> clazz, String ... mappings) {

    	if((object = mappingConvert(object, mappings)) == null || clazz == null){
    		return null;
    	}
    	if(object instanceof String){
    		return toJavaObject(object.toString(), clazz);
    	}
		return toJavaObject(object, clazz);
    }
    
    /**
     * Json对象转Java对象
     * @param list
     * @param clazz
     * @param mappings 指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
     * @return
     */
    public static <T> List<T> toJavaList(List<?> list, Class<T> clazz, String ... mappings) {

    	List<T> newList = new ArrayList<>();
    	for (Object object : list) {
    		newList.add(toJavaObject(object, clazz, mappings));
		}
    	return newList;
    }
    
    /**
     * Json对象转Java对象
     * @param object
     * @param clazz
     * @param extFieldOptions 不符合下划线转驼峰形式的字段，可以在此指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
     * @return
     */
    public static <T> List<T> toJavaListWithSnake(List<?> list, Class<T> clazz, String ... extFieldOptions) {

    	List<T> newList = new ArrayList<>();
    	for (Object object : list) {
    		newList.add(toJavaObjectWithSnake(object, clazz, extFieldOptions));
		}
    	return newList;
    }
    
	/**
	 * 将不确定的json对象转成Map, 不确定json对象：json字符串, Map, 其他Java对象
	 * @param object
	 * @return
	 */
	public static Map<String, Object> parseJSON(Object object){
		return parseJSON(object, null, null);
	}
    
    /**
	 * 将不确定的json对象转成Map, 不确定json对象：json字符串, Map, 其他Java对象
	 * @param object
	 * @return
	 */
    @SuppressWarnings("unchecked")
	public static Map<String, Object> parseJSON(Object object, Class<?> targetClass, Class<?> mixinSource){
		if(object == null){
			return null;
		}
		Map<String,Object> map ;
		if(object instanceof String){
			map = toJavaObject((String)object, Map.class);
		}else if(object instanceof Map){
			map = (Map<String,Object>)object;
		}else{
			map = toJavaObject(toJsonString(object, true, false, targetClass, mixinSource), Map.class);
		}
		return map;
	}
	
	public static List<Map<String, Object>> parseArray(Object object){
		
		return parseArray(object, newTypeRf());
	}
	
	/**
	 * 将不确定的json对象转成Map, 不确定json对象：json字符串, Map, 其他Java对象
	 * @param object
	 * @param tr  TypeReference, 例：new TypeReference<List<XXXEntity>>() {}, new TypeReference<Set<XXXEntity>>() {}
	 * @param mappings 指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
	 * @return
	 */
	public static <T> List<T> parseArray(Object object, TypeReference<List<T>> tr, String ... mappings){
		
		object = mappingConvert(object, mappings);
		if(object == null){
    		return Collections.emptyList();
    	}
		
		return toGenericObject(object, tr);
	}
	
	/**
	 * @param object
	 * @param tr  TypeReference, 例：new TypeReference<List<XXXEntity>>() {}, new TypeReference<Set<XXXEntity>>() {}
	 * @param extFieldOptions 不符合下划线转驼峰形式的字段，可以在此指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
	 * @return
	 */
	public static <T> List<T> parseArrayWithSnake(Object object, TypeReference<List<T>> tr, String ... extFieldOptions){
		
		object = snakeCaseConvert(object, extFieldOptions);
		return parseArray(object, tr);
	}
	
    /**
     * JSON串转换为Java泛型对象，可以是各种类型。
     *
     * @param <T>
     * @param object JSON对象
     * @param tr  TypeReference, 例：new TypeReference<List<XXXEntity>>() {}, new TypeReference<Set<XXXEntity>>() {}
     * @param mappings 指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
     * @return List对象列表
     */
	public static <T> T toGenericObject(Object object, TypeReference<T> tr, String ... mappings) {

    	if((object = mappingConvert(object, mappings)) == null || tr == null){
    		return null;
    	}
    	
		String jsonString = object instanceof String ? toString(object) : toJsonString(object);
    	if (StringUtils.isBlank(jsonString)) {
            return null;
        } 
        
        try {
            return objectMapper.readValue(jsonString, tr);
        } catch (Exception e) {
        	logger.error("json串转换为Java泛型对象异常", e);
			throw new BaseException("json串转换为Java泛型对象异常", e);
        }
    }
	
	/**
	 * JSON串转换为Java泛型对象，可以是各种类型
	 *
	 * @param <T>
	 * @param object JSON对象
	 * @param tr  TypeReference, 例：new TypeReference<List<XXXEntity>>() {}, new TypeReference<Set<XXXEntity>>() {}
	 * @param extFieldOptions 不符合下划线转驼峰形式的字段，可以在此指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
	 * @return List对象列表
	 * @return
	 */
	public static <T> T toObjectWithSnake(Object object, TypeReference<T> tr, String ... extFieldOptions) {
		
		if((object = snakeCaseConvert(object, extFieldOptions)) == null || tr == null){
			return null;
		}
		return toGenericObject(toJsonString(object), tr);
	}
	
    /**
     * 将对象属性下划线转驼峰
     * @param object
     * @param extFieldOptions 不符合下划线转驼峰形式的字段，可以在此指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
     * @return
     */
    @SuppressWarnings("unchecked")
	public static Object snakeCaseConvert(Object object, String ... extFieldOptions){
    	if(object == null){
    		return null;
    	}
    	if(object instanceof Collection){
    		Collection<Object> list = (Collection<Object>)object;
    		List<Object> newList = new ArrayList<>();
    		for (Object obj : list) {
    			newList.add(snakeCaseConvertSingle(obj, extFieldOptions));
			}
    		return newList;
    	}
    	if(object.getClass().isArray()){
    		Object[] arr = (Object[])object;
    		Object[] newArr = new Object[arr.length];
    		for (int i = 0; i < arr.length; i++) {
    			newArr[i] = snakeCaseConvertSingle(arr[i], extFieldOptions);
			}
    		return newArr;
    	}
		return snakeCaseConvertSingle(object, extFieldOptions);
    }
    
    @SuppressWarnings("unchecked")
    private static Object snakeCaseConvertSingle(Object object, String ... extFieldOptions){
    	if(object instanceof String){
    		if(StringUtils.isBlank(Objects.toString(object, null))){
    			return null;
    		}
    		return snakeCase(toJavaObject(object.toString(), Map.class), extFieldOptions);
    	}else if(object instanceof Map){
    		return snakeCase((Map<String, Object>)object, extFieldOptions);
    	}
    	return snakeCase(toJavaObject(toJsonString(object), Map.class), extFieldOptions);
    }
    
    /**
     * 将map对象的属性 下划线转驼峰
     * @param map
     * @param extFieldOptions 不符合下划线转驼峰形式的字段，可以在此指定映射关系, 如 nick_name=>name,可以将nick_name字段映射到name属性上
     * @return
     */
    public static Map<String, Object> snakeCase(Map<String, Object> map, String ... extFieldOptions){
    	if(CollectionUtil.isEmpty(map)){
    		return map;
    	}
    	boolean isHasExtOp = extFieldOptions != null && extFieldOptions.length > 0;
    	Map<String, String> fieldMap = null;
    	if(isHasExtOp){
    		fieldMap = splitExtFieldOptions(extFieldOptions);
    	}
    	Map<String, Object> newMap = createMap(map);
    	for (Entry<String, Object> entry : map.entrySet()) {
    		if(isHasExtOp && fieldMap.containsKey(entry.getKey())){
    			newMap.put(fieldMap.get(entry.getKey()), entry.getValue());
    		}else{
    			newMap.put(toCamel(entry.getKey()), entry.getValue());
    		}
		}
    	return newMap;
    }
    
    /**
     * 分隔字段
     * @param fields
     * @return
     * @author lam
     */
    private static Map<String, String> splitExtFieldOptions(String[] fields) {
        String[] fssTmp = null;
        Map<String, String> fieldMap = new HashMap<>();
        for (int i = 0;i<fields.length;i++) {
            if(fields[i].indexOf("=>") > -1 && (fssTmp = fields[i].split("=>")).length > 1){
            	fieldMap.put(StringUtils.trim(fssTmp[0]), StringUtils.trim(fssTmp[1]));
            }
        }
        return fieldMap;
    }
    
    /**
     * 根据mapping将对象转换为新的对象
     * @param object
     * @param mappings 指定映射关系, 如 nick_name=>name,可以将nick_name字段转换为name属性
     * @return
     */
    @SuppressWarnings("unchecked")
    public static Object mappingConvert(Object object, String ... mappings){
    	if(object == null || mappings == null || mappings.length < 1){
    		return object;
    	}
    	if(object instanceof Collection){
    		Collection<Object> list = (Collection<Object>)object;
    		List<Object> newList = new ArrayList<>(list.size());
    		for (Object obj : list) {
    			newList.add(mappingConvertSingle(obj, mappings));
    		}
    		return newList;
    	}
    	if(object.getClass().isArray()){
    		Object[] arr = (Object[])object;
    		Object[] newArr = new Object[arr.length];
    		for (int i = 0; i < arr.length; i++) {
    			newArr[i] = mappingConvertSingle(arr[i], mappings);
    		}
    		return newArr;
    	}
    	return mappingConvertSingle(object, mappings);
    }
    
    @SuppressWarnings("unchecked")
	private static Object mappingConvertSingle(Object object, String ... mappings){
    	if(object instanceof String){
    		if(StringUtils.isBlank(Objects.toString(object, null))){
    			return null;
    		}
    		return fieldConvert(toJavaObject(object.toString(), Map.class), mappings);
    	}else if(object instanceof Map){
    		return fieldConvert((Map<String, Object>)object, mappings);
    	}
		return fieldConvert(toJavaObject(toJsonString(object), Map.class), mappings);
    }
    
    /**
     * 根据mapping将map对象转换为新的map对象
     * @param map
     * @param mappings 指定映射关系, 如 nick_name=>name,可以将nick_name字段转换为name属性
     * @return
     */
    public static Map<String, Object> fieldConvert(Map<String, Object> map, String ... mappings){
    	if(CollectionUtil.isEmpty(map) || mappings == null || mappings.length < 1){
    		return map;
    	}
    	Map<String, String> fieldMap = splitMappings(mappings);
    	Map<String, Object> newMap = createMap(map);
    	Object value ;
    	for (Entry<String, String> entry : fieldMap.entrySet()) {
    		value = map.get(StringUtils.trim(entry.getKey()));
    		if(value!=null){
    			newMap.put(StringUtils.trim(entry.getValue()), value);
    		}
    	}
    	return newMap;
    }

	private static Map<String, Object> createMap(Map<String, Object> map) {
    	if(map.getClass() == HashMap.class){
    		return new HashMap<>(map.size());
    	}else if(map.getClass() == TreeMap.class){
    		return new TreeMap<>();
    	}
    	return new LinkedHashMap<>(map.size());
	}

    /**
     * 分隔字段
     * @param fields
     * @return
     * @author lam
     */
    private static Map<String, String> splitMappings(String[] mappings) {
        String[] fssTmp = null;
        Map<String, String> fieldMap = new HashMap<>();
        for (int i = 0;i<mappings.length;i++) {
        	fssTmp = split2Two(mappings[i]);
        	fieldMap.put(StringUtils.trim(fssTmp[0]), StringUtils.trim(fssTmp[1]));
        }
        return fieldMap;
    }
    
    private static String[] split2Two(String str){
    	if(str.indexOf("=>") > -1){
    		String[] fssTmp = str.split("=>");
    		if(fssTmp.length > 1){
    			return fssTmp;
    		}
    	}
    	return new String[]{str, str};
    }
    
    /**
	 * 下划线转驼峰
	 * @param str
	 * @return
	 */
    public static String toCamel(String str) {
    	if(StringUtils.isBlank(str)){
    		return str;
    	}
    	return toCamel(new StringBuffer(str)).toString();
    }
	/**
	 * 下划线转驼峰
	 * @param str
	 * @return
	 */
	public static StringBuffer toCamel(StringBuffer str) {
		//利用正则删除下划线，把下划线后一位改成大写
		Pattern pattern = Pattern.compile("_(\\w)");
		Matcher matcher = pattern.matcher(str);
		StringBuffer sb = new StringBuffer(str);
		if(matcher.find()) {
			sb = new StringBuffer();
			//将当前匹配子串替换为指定字符串，并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里。
			//正则之前的字符和被替换的字符
			matcher.appendReplacement(sb, matcher.group(1).toUpperCase());
			//把之后的也添加到StringBuffer对象里
			matcher.appendTail(sb);			
		}else {
			return sb;
		}	
		return toCamel(sb);
	}
	
	public static String toUnderline(String str) {
    	if(StringUtils.isBlank(str)){
    		return str;
    	}
    	return toUnderline(new StringBuffer(str)).toString();
    }
	
	/**
	 * 驼峰转下划线
	 * @param str
	 * @return
	 */
	public static StringBuffer toUnderline(StringBuffer str) {
		Pattern pattern = Pattern.compile("[A-Z]");
		Matcher matcher = pattern.matcher(str);
		StringBuffer sb = new StringBuffer(str);
		if(matcher.find()) {
			sb = new StringBuffer();
			//将当前匹配子串替换为指定字符串，并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里。
			//正则之前的字符和被替换的字符
			matcher.appendReplacement(sb,"_"+matcher.group(0).toLowerCase());
			//把之后的也添加到StringBuffer对象里
			matcher.appendTail(sb);			
		}else {
			return sb;
		}	
		return toUnderline(sb);
	}
	
	public static BigDecimal multiply(BigDecimal d1, BigDecimal d2){
		if(d1 == null || d2 == null){
			return null;
		}
		return d1.multiply(d2);
	}
	
	public static String toString(Object obj){
		return toString(obj, null);
	}
	
	public static String toString(Object o, String nullDefault) {
        return (o != null) ? o.toString() : nullDefault;
    }
 
	public static BigDecimal toBigDecimal(Object obj){
		if(obj == null){
			return null;
		}
		String str = Objects.toString(obj, null);
		if(StringUtils.isBlank(str)){
			return null;
		}
		return new BigDecimal(str);
	}
	
	public static Integer toInteger(Object obj){
		if(obj == null){
			return null;
		}
		String str = Objects.toString(obj, null);
		if(StringUtils.isBlank(str)){
			return null;
		}
		return Integer.parseInt(str);
	}
	
    public static boolean isJson(String json) {
        try {
            return toJavaObject(json, Map.class) != null;
        } catch (Exception e) {
        	logger.debug(e.getMessage(), e);
        }
        return false;
    }

    /**
     * json字符串压缩方法
     * @param json json串
     * @return 压缩后的json串
     * */
    public static String compressJson(String json, String charset) {
    	
        if (StringUtils.isBlank(json)) {
            return json;
        }
        if (StringUtils.isBlank(charset)) {
        	charset = "utf-8";
        }
        
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();GZIPOutputStream gzip = new GZIPOutputStream(out);){
			gzip.write(json.getBytes());
			return out.toString(charset);
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage(), e);
			throw new BaseException("压缩json串时编码不支持", e);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			throw new BaseException("压缩json串异常", e);
		}
    }
    
    /**
     * 字符串的解压
     * @param str 
     * @return 解压缩后的字符串
     */
    public static String unCompressJson(String str, String charset) {
    	
    	if (StringUtils.isBlank(str)) {
            return str;
        }
    	if (StringUtils.isBlank(charset)) {
        	charset = "utf-8";
        }
    	
        try (ByteArrayOutputStream out = new ByteArrayOutputStream();GZIPInputStream gzip = new GZIPInputStream(new ByteArrayInputStream(str.getBytes(charset)));){
			byte[] buffer = new byte[256];
			int n = 0;
			while ((n = gzip.read(buffer)) >= 0) {
			    out.write(buffer, 0, n);
			}
			return out.toString(charset);
		} catch (UnsupportedEncodingException e) {
			logger.error(e.getMessage(), e);
			throw new BaseException("解压json串时编码不支持", e);
		} catch (IOException e) {
			logger.error(e.getMessage(), e);
			throw new BaseException("解压json串异常", e);
		}
    }
    
}
